/* Field.h
Michael Zahniser, 2008

Header file for the Field class, which represents a single field in a form
that is displayed and edited through ncurses.
*/

#ifndef __MZ_FIELD_H__
#define __MZ_FIELD_H__

#include <string>

using std::string;



class Field {
public:
	Field(const string &label);
	
	// Draw this field in the given row.
	void Draw(int y, int x = 0) const;
	// Process the given key press.
	// Returns true if this should result in switching to the next field.
	bool HandleKey(int key);

	// Get the number of characters used to display this field's label and contents.
	int Width() const;
	// Get the label of this field.
	const string &Label();
	// Get the default value of this field.
	const string &DefaultValue();
	// Get the current value of this field.
	const string &Value();

	// Callback functions should be in this form.
	typedef bool (*Callback)(string &entry, void *data);
	// This function is called whenever the text of a field changes, to check whether the
	// current contents of the field are valid. The validation function can either return
	// false if a field is invalid, or edit the field to make it valid and return true.
	Field &OnValidate(Callback callback = NULL, void *data = NULL);
	// This function is called whenever the user presses <tab>, to perform tab-completion.
	Field &OnComplete(Callback callback = NULL, void *data = NULL);
	// This function is called when the user presses <enter>.
	Field &OnEnter(Callback callback = NULL, void *data = NULL);
	// Set the default value of this field.
	// If a default is set, it is used if the user presses <enter> on an empty field.
	Field &SetDefault(const string &defaultValue);
	

private:
	// Validate the current text contents.
	void Validate();
	
	
private:
	class Caller {
	public:
		Caller() : callback(NULL), data(NULL) {}
		
		bool operator()(string &entry) const
		{
			return !callback || (*callback)(entry, data);
		}
		
		void Set(Callback callback, void *data)
		{
			this->callback = callback;
			this->data = data;
		}
		
	private:
		Callback callback;
		void *data;
	};
	
	
private:
	string label;
	string defaultValue;
	string fullLabel;
	string value;
	
	Caller onValidate;
	Caller onComplete;
	Caller onEnter;
	
	bool isValid;
};



#endif
